{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8f486159",
   "metadata": {},
   "source": [
    "| [01_base/04_字典类型_dict.ipynb](https://github.com/shibing624/python-tutorial/blob/master/01_base/04_字典类型_dict.ipynb)  | Python字典  |[Open In Colab](https://colab.research.google.com/github/shibing624/python-tutorial/blob/master/01_base/04_字典类型_dict.ipynb) |\n",
    "\n",
    "\n",
    "# dict\n",
    "\n",
    "字典 dictionary ，在一些编程语言中也称为 hash ， map ，\n",
    "是一种由键值对组成的数据结构。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "5a63c0d4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'dict'>\n",
      "<class 'dict'>\n"
     ]
    }
   ],
   "source": [
    "a = {}\n",
    "print(type(a))  # <type 'dict'>\n",
    "a = dict()\n",
    "print(type(a))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "534b3c64",
   "metadata": {},
   "source": [
    "### 操作dict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "518a6eca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'f': 'num 1', 's': 'num 2'}\n"
     ]
    }
   ],
   "source": [
    "# 插入键值\n",
    "a['f'] = 'num 1'\n",
    "a['s'] = 'num 2'\n",
    "print(a)  # {u's': u'num 2', u'f': u'num 1'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "25d511c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num 2\n"
     ]
    }
   ],
   "source": [
    "# 查看键值\n",
    "print(a['s'])  # num 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "28b6d285",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'f': 'num 3', 's': 'num 2'}\n"
     ]
    }
   ],
   "source": [
    "# 更新\n",
    "a['f'] = 'num 3'\n",
    "print(a)  # {u's': u'num 2', u'f': u'num 3'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "c6a5dfd6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num 1\n",
      "num 3\n"
     ]
    }
   ],
   "source": [
    "# 初始化字典\n",
    "a = {'first': 'num 1', 'second': 'num 2', 3: 'num 3'}\n",
    "print(a['first'])  # num 1\n",
    "print(a[3])  # num 3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d3d846bb",
   "metadata": {},
   "source": [
    "Python中不能用支持用数字索引按顺序查看字典中的值，\n",
    "而且数字本身也有可能成为键值，这样会引起混淆:\n",
    "\n",
    "a[0] 会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "b1f82a5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "error: 0\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    print(a[0])\n",
    "except KeyError as e:\n",
    "    print('error:', e)\n",
    "#a[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bd32d97",
   "metadata": {},
   "source": [
    "### dict的应用示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "e421c72b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{500: {'mag': 0.05, 'width': 20}, 760: {'mag': 0.04, 'width': 25}, 3001: {'mag': 0.05, 'width': 80}, 4180: {'mag': 0.03, 'width': 30}}\n"
     ]
    }
   ],
   "source": [
    "# 定义四个字典\n",
    "e1 = {'mag': 0.05, 'width': 20}\n",
    "e2 = {'mag': 0.04, 'width': 25}\n",
    "e3 = {'mag': 0.05, 'width': 80}\n",
    "e4 = {'mag': 0.03, 'width': 30}\n",
    "\n",
    "# 以字典作为值传入新的字典\n",
    "events = {500: e1, 760: e2, 3001: e3, 4180: e4}\n",
    "# {760: {u'width': 25, u'mag': 0.04},\n",
    "# 3001: {u'width': 80, u'mag': 0.05},\n",
    "# 500: {u'width': 20, u'mag': 0.05},\n",
    "# 4180: {u'width': 30, u'mag': 0.03}}\n",
    "print(events)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "932f6517",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'first': 'Sam', 'last': 'Malone', 'name': 35}, {'first': 'Woody', 'last': 'Boyd', 'name': 21}, {'first': 'Norm', 'last': 'Peterson', 'name': 34}, {'first': 'Diane', 'last': 'Chambers', 'name': 33}]\n"
     ]
    }
   ],
   "source": [
    "# 另一个例子\n",
    "people = [\n",
    "    {'first': 'Sam', 'last': 'Malone', 'name': 35},\n",
    "    {'first': 'Woody', 'last': 'Boyd', 'name': 21},\n",
    "    {'first': 'Norm', 'last': 'Peterson', 'name': 34},\n",
    "    {'first': 'Diane', 'last': 'Chambers', 'name': 33}\n",
    "]\n",
    "# [{'first': 'Sam', 'last': 'Malone', 'name': 35},\n",
    "#  {'first': 'Woody', 'last': 'Boyd', 'name': 21},\n",
    "#  {'first': 'Norm', 'last': 'Peterson', 'name': 34},\n",
    "#  {'first': 'Diane', 'last': 'Chambers', 'name': 33}]\n",
    "print(people)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62fb939d",
   "metadata": {},
   "source": [
    "使用 dict 初始化字典："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "ad89b640",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': 'lili', 'sex': 'female', 'age': 32, 'address': 'beijing'}\n"
     ]
    }
   ],
   "source": [
    "# 除了通常的定义方式，还可以通过 dict() 转化来生成字典：\n",
    "my_dict = dict([('name', 'lili'),\n",
    "                ('sex', 'female'),\n",
    "                ('age', 32),\n",
    "                ('address', 'beijing')])\n",
    "# {u'age': 32,\n",
    "# u'address': u'beijing',\n",
    "# u'name': u'lili',\n",
    "# u'sex': u'female'}\n",
    "print(my_dict)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19958d69",
   "metadata": {},
   "source": [
    "利用索引直接更新键值对："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "34af8e8e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': 'lili', 'sex': 'female', 'age': 33, 'address': 'beijing'}\n"
     ]
    }
   ],
   "source": [
    "my_dict['age'] += 1\n",
    "print(my_dict)  # u'age': 33"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11a2c3d9",
   "metadata": {},
   "source": [
    "dict可以使用元组作为键值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "4155b2d6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{('New York', 'Seattle'): 100,\n",
       " ('Austin', 'New York'): 200,\n",
       " ('New York', 'Austin'): 400}"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 例如，可以用元组做键来表示从第一个城市飞往第二个城市航班数的多少：\n",
    "connections = {}\n",
    "connections[('New York', 'Seattle')] = 100\n",
    "connections[('Austin', 'New York')] = 200\n",
    "connections[('New York', 'Austin')] = 400\n",
    "connections"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "1cec223a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "200\n",
      "400\n"
     ]
    }
   ],
   "source": [
    "# 元组是有序的，\n",
    "# 因此 ('New York', 'Austin') 和 ('Austin', 'New York') 是两个不同的键：\n",
    "print(connections[('Austin', 'New York')])  # 200\n",
    "print(connections[('New York', 'Austin')])  # 400"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e2f18bd1",
   "metadata": {},
   "source": [
    "## 字典方法\n",
    "get 方法 : d.get(key, default = None)\n",
    "\n",
    "之前已经见过，用索引可以找到一个键对应的值，\n",
    "但是当字典中没有这个键的时候，Python会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "687c1ae6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "a = {'first': 'num 1', 'second': 'num 2'}\n",
    "# error:\n",
    "# print(a['third'])\n",
    "\n",
    "# get 返回字典中键 key 对应的值，\n",
    "# 如果没有这个键，返回 default 指定的值（默认是 None ）。\n",
    "print(a.get('third'))  # None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "5d1f66ea",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'num 0'"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 指定默认值参数：\n",
    "b = a.get(\"three\", \"num 0\")\n",
    "b  # num 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6d853a8",
   "metadata": {},
   "source": [
    "### pop 方法删除元素\n",
    "pop 方法可以用来弹出字典中某个键对应的值，同时也可以指定默认参数：\n",
    "\n",
    "d.pop(key, default = None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "90c93e59",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "num 1\n",
      "{'second': 'num 2'}\n"
     ]
    }
   ],
   "source": [
    "a = {'first': 'num 1', 'second': 'num 2'}\n",
    "c = a.pop('first')\n",
    "print(c)  # num 1\n",
    "print(a)  # {u'second': u'num 2'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "a1ef0630",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "not exist\n"
     ]
    }
   ],
   "source": [
    "# 弹出不存在的键值：\n",
    "d = a.pop(\"third\", 'not exist')\n",
    "print(d)  # not exist"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "2d013977",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'second': 'num 2'}\n"
     ]
    }
   ],
   "source": [
    "# 与列表一样，del 函数可以用来删除字典中特定的键值对，例如：\n",
    "a = {'first': 'num 1', 'second': 'num 2'}\n",
    "del a[\"first\"]\n",
    "print(a)  # {u'second': u'num 2'}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3266dc0b",
   "metadata": {},
   "source": [
    "### update方法更新字典\n",
    "\n",
    "之前已经知道，可以通过索引来插入、修改单个键值对，\n",
    "但是如果想对多个键值对进行操作，这种方法就显得比较麻烦，好在有 update 方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "9030d255",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'name': 'lucy', 'sex': 'female', 'age': 32, 'address': 'beijing', 'marriage': 'single'}\n"
     ]
    }
   ],
   "source": [
    "my_dict = dict([('name', 'lili'),\n",
    "                ('sex', 'female'),\n",
    "                ('age', 32),\n",
    "                ('address', 'beijing')])\n",
    "# 把 ‘lili' 改成 'lucy'，同时插入 'single' 到 'marriage'\n",
    "dict_update = {'name': 'lucy', 'marriage': 'single'}\n",
    "my_dict.update(dict_update)\n",
    "print(my_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "d8dde117",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'address': 'beijing',\n",
      " 'age': 32,\n",
      " 'marriage': 'single',\n",
      " 'name': 'lucy',\n",
      " 'sex': 'female'}\n"
     ]
    }
   ],
   "source": [
    "import pprint\n",
    "# {u'marriage': u'single',\n",
    "# u'name': u'lucy',\n",
    "# u'address': u'beijing',\n",
    "# u'age': 32,\n",
    "# u'sex': u'female'}\n",
    "pprint.pprint(my_dict)  # 华丽丽的显示方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "d23cf8e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'name': 'lucy',\n",
       " 'sex': 'female',\n",
       " 'age': 32,\n",
       " 'address': 'beijing',\n",
       " 'marriage': 'single'}"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_dict # ipython的dict显示跟pprint的格式一样华丽"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2373e2df",
   "metadata": {},
   "source": [
    "通过关键词 `in` 查询字典中是否有该键："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "af366b06",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "barn = {'cows': 1, 'dogs': 5, 'cats': 3}\n",
    "# in 可以用来判断字典中是否有某个特定的键：\n",
    "print('chickens' in barn)  # False\n",
    "print('cows' in barn)  # True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "025acb3a",
   "metadata": {},
   "source": [
    "### keys 方法，values 方法和items 方法\n",
    "- `d.keys()` 返回一个由所有键组成的列表；\n",
    "- `d.values()` 返回一个由所有值组成的列表；\n",
    "- `d.items()` 返回一个由所有键值对元组组成的列表；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "dbc02f5d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "dict_keys(['cows', 'dogs', 'cats'])\n",
      "dict_values([1, 5, 3])\n",
      "dict_items([('cows', 1), ('dogs', 5), ('cats', 3)])\n"
     ]
    }
   ],
   "source": [
    "print(barn.keys())  # [u'cows', u'cats', u'dogs']\n",
    "print(barn.values())  # [1, 3, 5]\n",
    "print(barn.items())  # [(u'cows', 1), (u'cats', 3), (u'dogs', 5)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "171afe3a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cows 1\n",
      "dogs 5\n",
      "cats 3\n"
     ]
    }
   ],
   "source": [
    "for key, val in barn.items():\n",
    "    print(key, val)\n",
    "    # cows 1\n",
    "    # cats 3\n",
    "    # dogs 5"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cb51097",
   "metadata": {},
   "source": [
    "本节完。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f91533ab",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}